/*
 * f-ops.c
 *
 *  Created on: Oct 14, 2016
 *      Author: zhangzm
 */
#include <unistd.h>
#include "st.h"
#include "f-ops.h"

#define CHECK_ERROR_REDO() 									\
	if(ret < 0){											\
		LOG_ERROR("error pread/pwrite return %d %m", ret);	\
		if(errno == EINTR){									\
			goto redo;										\
		}													\
		return ret;											\
	}else if(ret < (ssize_t)count){							\
		LOG_ERROR("error pread/pwrite return %d %m", ret);	\
		goto redo;											\
	}

size_t ursax_iov_size(const struct iovec *iov, const unsigned int iov_cnt);

ssize_t st_pread(int fd, void* buf, size_t count, off_t offset)
{
	ssize_t ret = 0;
redo:
	ret = pread(fd, buf, count, offset);
	CHECK_ERROR_REDO();
	st_sleep(0);
	return ret;
}

ssize_t st_pwrite(int fd, const void *buf, size_t count, off_t offset)
{
	ssize_t ret = 0;
redo:
	ret = pwrite(fd, buf, count, offset);
	CHECK_ERROR_REDO();
	st_sleep(0);
	return ret;
}

ssize_t st_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	int count = ursax_iov_size(iov, iovcnt);
	ssize_t ret = 0;
redo:
	ret = preadv(fd, iov, iovcnt, offset);
	CHECK_ERROR_REDO();
	st_sleep(0);
	return ret;
}

ssize_t st_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	int count = ursax_iov_size(iov, iovcnt);
	ssize_t ret = 0;
redo:
	ret = pwritev(fd, iov, iovcnt, offset);
	CHECK_ERROR_REDO();
	st_sleep(0);
	return ret;
}

int st_fsync(int fd)
{
	int ret = fsync(fd);
	st_sleep(0);
	return ret;
}

int st_fdatasync(int fd)
{
	int ret = fdatasync(fd);
	st_sleep(0);
	return ret;
}

///////////////////////////////////////////////
int ignore_sleep_utime = 100;
ssize_t st_ignore_pread(int fd, void* buf, size_t count, off_t offset)
{
	st_usleep(ignore_sleep_utime);
	return count;
}

ssize_t st_ignore_pwrite(int fd, const void *buf, size_t count, off_t offset)
{
	st_usleep(ignore_sleep_utime);
	return count;
}

ssize_t st_ignore_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	st_usleep(ignore_sleep_utime);
	return ursax_iov_size(iov, iovcnt);
}

ssize_t st_ignore_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
{
	st_usleep(ignore_sleep_utime);
	return ursax_iov_size(iov, iovcnt);
}

int st_ignore_fsync(int fd)
{
	st_sleep(0);
	return 0;
}

int st_ignore_fdatasync(int fd)
{
	st_sleep(0);
	return 0;
}

size_t ursax_iov_size(const struct iovec *iov, const unsigned int iov_cnt)
{
	size_t len;
	unsigned int i;

	len = 0;
	for (i = 0; i < iov_cnt; i++) {
		len += iov[i].iov_len;
	}
	return len;
}